using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace GarbageTruck.TimeUnit
{

    public struct TimeUnits
    {
        public const string hour = "h";
        public const string minute = "m";
        public const string second = "s";
        public const string MiliSecondsecond = "f";
    }

    public class TimeUnit : ITemporalExpression
    {

        #region CONSTRUCTORS

        public TimeUnit()
        {
        }

        public TimeUnit(string expresion)
        {
            string[] parameters = expresion.Split(',');

            this.Number = int.Parse(parameters[0]);
            this.Unit = parameters[1];
            this.Start = DateTime.Parse(parameters[2]);
            this.Amount = TimeSpan.Parse(parameters[3]);
        }

        public TimeUnit(int number, string unit, DateTime start, TimeSpan amount)
        {
            this.Number = number;
            this.Unit = unit;
            this.Start = start;
            this.Amount = amount;
        }

        #endregion CONSTRUCTORS

        #region FIELDS

        private int m_Number;
        private string m_Unit;
        private DateTime m_Start;
        private TimeSpan m_Amount;

        #endregion FIELDS

        #region PROPERTIES

        public int Number
        {
            get { return m_Number; }
            set { m_Number = value; }
        }

        public string Unit
        {
            get { return m_Unit; }
            set { m_Unit = value; }
        }

        public DateTime Start
        {
            get { return m_Start; }
            set { m_Start = value; }
        }

        public TimeSpan Amount
        {
            get { return m_Amount; }
            set { m_Amount = value; }
        }


        #endregion PROPERTIES

        #region METHODS


        public bool Contains(DateTime dateTime)
        {
            int value = 0;
            DateTime startOcurrence = new DateTime();
            DateTime endOcurrence = new DateTime();

            if (dateTime >= this.Start && dateTime <= this.Start.AddTicks(this.Amount.Ticks)) return true;
            if (new DateTime(Start.Year, Start.Month, Start.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond) < Start) return false;

            switch (this.Unit)
            {
                case TimeUnits.hour:
                    value = dateTime.Hour - Start.Hour;
                    value = int.Parse(Math.Floor((double)(value / Number)).ToString());
                    startOcurrence = new DateTime(Start.Year, Start.Month, Start.Day, Start.Hour + Number * value, 0, 0);
                    break;

                case TimeUnits.minute:
                    value = (60 * (dateTime.Hour - Start.Hour)) + dateTime.Minute - Start.Minute;
                    value = int.Parse(Math.Floor((double)(value / Number)).ToString());
                    startOcurrence = new DateTime(Start.Year, Start.Month, Start.Day, Start.Hour, Start.Minute + Number * value, 0);
                    break;

                case TimeUnits.second:
                    value = (3600 * (dateTime.Hour - Start.Hour)) + (60 * (dateTime.Minute - Start.Minute)) + dateTime.Second - Start.Second;
                    value = int.Parse(Math.Floor((double)(value / Number)).ToString());
                    startOcurrence = new DateTime(Start.Year, Start.Month, Start.Day, Start.Hour, Start.Minute, Start.Second + Number * value);
                    break;
            }

            endOcurrence = startOcurrence.AddTicks(Amount.Ticks);
            if (dateTime >= startOcurrence && dateTime <= endOcurrence) return true;
            else return false;
        }

        public DateTime? GetNextOcurrence(DateTime dateTime)
        {
            return dateTime;
        }

        public DateTime? GetEventEnd(DateTime dateTime)
        {
            return dateTime;
        }

        public override string ToString()
        {
            return string.Format("TUNT({0},{1},{2},{3})",
                this.Number,
                this.Unit,
                this.Start.ToString("yyyy/MM/dd h:mm:ss.fff"),
                this.Amount.ToString());
        }

        #endregion METHODS

    }
}
